'''
Author: admin@attacker.club
Date: 2022-08-19 11:40:05
LastEditTime: 2022-08-19 12:17:49
Description: 
https://blog.51cto.com/u_9429042/2318210
https://blog.csdn.net/qq_55723966/article/details/122805019
'''
import socket
import struct
import json
 
# Zabbix Agent数据发送协议: <HEADER><DATALEN><DATA>
# <HEADER> - "ZBXD\x01" (5 bytes) , 头部信息"ZBXD"\协议版本"0x01"
# <DATALEN> - 数据长度 (8 bytes). 1将被格式化为01/00/00/00/00/00/00/00 (十六进制数8字节,64位数字)
# <DATA> - (为了不耗尽Zabbix-Server的内存,单次连接数据接收限制128M)
# Sender和Server建立Socket连接,发送key的数据(注意头部信息正确性),Server对数据进行处理响应的一个过程


class ZabbixSender:
    
    def __init__(self,server_host,server_port=10051):
        self.server_ip = server_host
        self.server_port = server_port
        self.zbx_header = 'ZBXD'
        self.zbx_sender_data = {
            'request':'sender data',
            'data':[]
            }
        self.zbx_version = 1
        self.send_data =''


    def AddData(self,host,key,value,clock=None):
        add_data = {'host':host,'key':key,'value':value}
        if clock != None:
            add_data['clock'] = clock

        self.zbx_sender_data['data'].append(add_data)

        return self.zbx_sender_data

    def ClearData(self):
        self.zbx_sender_data['data'] = []
        return self.zbx_sender_data

    def __MakeSendData(self):
        zbx_sender_json = json.dumps(self.zbx_sender_data,separators=(',',':'),ensure_ascii=False).encode('utf-8')
        json_byte = len(zbx_sender_json)
        self.send_data = struct.pack(f"<4sBq + {str(json_byte)}s{self.zbx_header}{self.zbx_version}{json_byte}{zbx_sender_json}")

    def Send(self):
        self.__MakeSendData()
        so = socket.socket()
        so.connect((self.server_ip,self.server_port))
        wobj = so.makefile('wb')
        wobj.write(self.send_data)
        wobj.close()
        robj = so.makefile('rb')
        recv_data = robj.read()
        robj.close()
        so.close()
        tmp_data = struct.unpack("<4sBq" + str(len(recv_data) - struct.calcsize("<4sBq")) + "s",recv_data)
        recv_json = json.loads(tmp_data[3])
        return recv_json

if __name__ == '__main__':
    max = 2 # 重复发送次数 
    sender = ZabbixSender('127.0.0.1')
    hostname = "Zabbix server" # 主机名一致
    for i in range(max):
        sender.AddData(f'{hostname}','test','sent data')

    # sender.AddData('Zabbix server','test','sent data' + str(num))
    # res = sender.Send()
    res = sender.Send()
    print(res)
